﻿using System.Collections.Generic;
using System.Linq;
using GameSchoolApplication.Models;
using System.Data;

namespace GameSchoolApplication.Repository
{
	public class TaskRepository
	{
		private GameSchoolWebContext _db = new GameSchoolWebContext();

		/// <summary>
		/// Returns a list of tests
		/// </summary>
		/// <returns></returns>
		public IEnumerable<Test> GetAllTests()
		{
			return _db.Tests.ToList();
		}

		/// <summary>
		/// Returns a single test
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
		public Test GetTestById(int id)
		{
			var test = _db.Tests.Where(m => m.TestId == id).SingleOrDefault();
			return test;
		}

		/// <summary>
		/// Add a test
		/// </summary>
		/// <param name="test"></param>
		public void AddTest(Test test)
		{
			_db.Tests.Add(test);
			_db.SaveChanges();
		}

		/// <summary>
		/// Deletes a test
		/// </summary>
		/// <param name="test"></param>
		public void DeleteTest(Test test)
		{
			_db.Tests.Remove(test);
			_db.SaveChanges();
		}

		/// <summary>
		/// Returns student points
		/// </summary>
		/// <param name="test"></param>
		/// <param name="student"></param>
		/// <returns></returns>
        public StudentTestPoints GetStudentTestPoints(Test test, Person student)
        {
            return _db.StudentTestPoints.Where(st => st.TestId == test.TestId && st.StudentId == student.Id).SingleOrDefault();
        }

		/// <summary>
		/// Return a Student test point by id
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
        public StudentTestPoints GetStudentTestPoints(int id)
        {
            return _db.StudentTestPoints.Where(st => st.Id == id).SingleOrDefault();
        }

		/// <summary>
		/// Hand in assignment
		/// </summary>
		/// <param name="handIn"></param>
        public void AddStudentTestPoints(StudentTestPoints handIn)
        {
            _db.StudentTestPoints.Add(handIn);
            _db.SaveChanges();
        }

		/// <summary>
		/// Grade to test
		/// </summary>
		/// <param name="grade"></param>
        public void UpdateStudentTestPoints(StudentTestPoints grade)
        {
            Test test = _db.Tests.Where(t => t.TestId == grade.TestId).SingleOrDefault();
            UpdatePointChain(grade.StudentId, test.LevelId, grade.Points);
            _db.Entry(grade).State = EntityState.Modified;
            _db.SaveChanges();
        }

		/// <summary>
		/// Updates the student points database
		/// </summary>
		/// <param name="studentId"></param>
		/// <param name="levelId"></param>
		/// <param name="points"></param>
        private void UpdatePointChain(int studentId, int levelId, int? points)
        {
            if (points.HasValue)
            {
                StudentLevelPoints levelEntry = _db.StudentLevelPoints.Where(sl => sl.StudentId == studentId && sl.LevelId == levelId).SingleOrDefault();
                levelEntry.Points = (levelEntry.Points == null ? 0 : levelEntry.Points) + points;
                StudentPoints enrollment = _db.StudentPoints.Where(sp => sp.StudentId == studentId && sp.GameId == levelEntry.Level.GameId).SingleOrDefault();
                enrollment.Points = (enrollment.Points == null ? 0 : enrollment.Points) + points;
                _db.Entry(levelEntry).State = EntityState.Modified;
                _db.Entry(enrollment).State = EntityState.Modified;
            }
        }

		/// <summary>
		/// Update students grade
		/// </summary>
		/// <param name="grade"></param>
        public void UpdateStudentAssignmentPoints(StudentAssignmentPoints grade)
        {
            Assignment assignment = _db.Assignments.Where(a => a.AssignmentId == grade.AssignmentId).SingleOrDefault();
            UpdatePointChain(grade.StudentId, assignment.LevelId, grade.Points);
            _db.Entry(grade).State = EntityState.Modified;
            _db.SaveChanges();
        }

		/// <summary>
		/// Adds question
		/// </summary>
		/// <param name="question"></param>
        public void AddQuestion(Question question)
        {
            _db.Questions.Add(question);
            _db.SaveChanges();
        }

		/// <summary>
		/// Returns a question by id
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
        public Question GetQuestion(int id)
        {
            return _db.Questions.Where(q => q.QuestionId == id).SingleOrDefault();
        }

		/// <summary>
		/// Add a answer 
		/// </summary>
		/// <param name="answer"></param>
        public void AddAnswer(Answer answer)
        {
            _db.Answers.Add(answer);
            _db.SaveChanges();
        }

		/// <summary>
		/// Return a list of all assignments
		/// </summary>
		/// <returns></returns>
		public IEnumerable<Assignment> GetAllAssignments()
		{
			return _db.Assignments.ToList();
		}

		/// <summary>
		/// Returns assingment by id
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
		public Assignment GetAssignmentById(int id)
		{
			var assignment = _db.Assignments.Where(m => m.AssignmentId == id).SingleOrDefault();
			return assignment;
		}

		/// <summary>
		/// Adds a assignment
		/// </summary>
		/// <param name="assignment"></param>
		public void AddAssignment(Assignment assignment)
		{
			_db.Assignments.Add(assignment);
			_db.SaveChanges();
		}

		/// <summary>
		/// Delete assignment
		/// </summary>
		/// <param name="assignment"></param>
		public void DeleteAssignment(Assignment assignment)
		{
			_db.Assignments.Remove(assignment);
			_db.SaveChanges();
		}

		/// <summary>
		/// Sends the hand in of a assignment to the database
		/// </summary>
		/// <param name="handIn"></param>
        public void AddStudentAssignmentPoints(StudentAssignmentPoints handIn)
        {
            _db.StudentAssignmentsPoints.Add(handIn);
            _db.SaveChanges();
        }

		/// <summary>
		/// Gets a student assignment
		/// </summary>
		/// <param name="assignment"></param>
		/// <param name="student"></param>
		/// <returns></returns>
        public StudentAssignmentPoints GetStudentAssignmentPoints(Assignment assignment, Person student)
        {
            return _db.StudentAssignmentsPoints.Where(sa => sa.AssignmentId == assignment.AssignmentId && sa.StudentId == student.Id).SingleOrDefault();
        }

		/// <summary>
		/// Returns a single instance of assignment by id
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
        public StudentAssignmentPoints GetStudentAssignmentPoints(int id)
        {
            return _db.StudentAssignmentsPoints.Where(sa => sa.Id == id).SingleOrDefault();
        }

	}
}